package com.hbnu.service;

import java.io.*;
import java.net.Socket;

import com.hbnu.dao.UserDao;
import com.hbnu.pojo.MyThread;
import com.hbnu.pojo.Record;
import com.hbnu.pojo.User;
import com.hbnu.util.PhoneCode;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ServerTread implements Runnable{
    private Socket socket;
    private UserDao userDao=new UserDao();
    private static final int PLAYERS_PER_GAME = 4;
    private ExecutorService threadPool = Executors.newFixedThreadPool(10);
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private static ConcurrentHashMap<Socket, String> onlineUser = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Socket,String> apartment = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Socket,MyThread> waitingThread = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Socket,PrintWriter> allOut = new ConcurrentHashMap<>();
    private static ConcurrentHashMap<Socket,BufferedReader> allInput = new ConcurrentHashMap<>();

    public ServerTread(Socket socket) throws IOException {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            page(socket);
            if(!Thread.currentThread().isInterrupted()){
                mainPage(socket);
            }
        } catch (Exception e) {
            System.out.println("玩家["+onlineUser.get(socket)+"]已强制下线");
            onlineUser.remove(socket);
            Thread thread = Thread.currentThread();
            thread.stop();
        }
    }

    private void page(Socket socket) throws Exception{
            PrintWriter out =new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8),true);
            BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
            boolean flag=true;
            try {
                while (flag){
                    out.println("****************************\n欢迎来到liars-bar\n1、登录\t2、注册\t3、找回密码\t4、退出");
                    int number = Integer.parseInt(in.readLine());
                    switch (number) {
                        case 1:
                            flag=login(out,in);
                            break;
                        case 2:
                            registers(out,in);
                            break;
                        case 3:
                            findPassword(out,in);
                            break;
                        case 4:
                            Thread thread = Thread.currentThread();
                            thread.interrupt();
                        default:
                            out.println("输入无效");
                    }
                    if(Thread.currentThread().isInterrupted()){
                        break;
                    }
                }
            } catch (java.net.SocketException e) {
                System.out.println("客户端连接被重置，连接已断开。");
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

    private void findPassword(PrintWriter out,BufferedReader in) {
        try {
            out.println("请输入您的电话号码：");
            String phoneNumber = in.readLine();
            User user=userDao.findPasswordByPhone(phoneNumber);
            if (user ==null) {
                out.println("号码不存在！");
            }else {
                out.println("请输入验证码：");
                PhoneCode phonecode = new PhoneCode();
                String code = phonecode.getCode();
                phonecode.sendCode(phoneNumber,code,2);
                for (int i = 0;i<3;i++) {
                    if (code.equals(in.readLine())) {
                        out.println("请输入您新密码");
                        String newPassword = in.readLine();
                        boolean updateFlag = userDao.updatePasswordByPhone(phoneNumber,newPassword);
                        if (updateFlag) {
                            out.println("修改成功！");
                            out.println("该账号名称为："+user.getName());
                        } else {
                            out.println("修改失败！");
                        }
                        break;
                    } else {
                        out.println("验证码错误,还有" + (3 - (i + 1)) + "次机会");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void registers(PrintWriter out,BufferedReader in) {
        try {
            out.println("请输入您的昵称");
            String name=in.readLine();
            User user = userDao.findUserByusername(name);
            if (user == null) {
                out.println("请输入您的密码:");
                String password=in.readLine();
                out.println("请输入您的电话号码:");
                String phoneNumber=in.readLine();
                User user1=userDao.findPasswordByPhone(phoneNumber);
                if (user1 ==null) {
                    out.println("请输入注册码：");
                    PhoneCode phonecode = new PhoneCode();
                    String code = phonecode.getCode();
                    phonecode.sendCode(phoneNumber,code,1);
                    for (int i = 0;i<3;i++) {
                        if (code.equals(in.readLine())) {
                            boolean createFlag=userDao.creatUser(name,password,phoneNumber);
                            if (createFlag) {
                                out.println("创建成功");
                            }else {
                                out.println("创建失败");
                            }
                            break;
                        }else {
                            out.println("验证码错误,还有"+(3-(i+1))+"次机会");
                        }
                    }
                }else {
                    out.println("该号码已注册！");
                }
            }else {
                out.println("用户已存在！\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private boolean login(PrintWriter out,BufferedReader in) {
        try {
            out.println("请输入您的账号与您的密码");
            String name=in.readLine();
            String password=in.readLine();
            User user =userDao.findUserByusernamAndpassword(name,password);
            if (user == null) {
                out.println("用户名或密码错误\n");
            } else if (onlineUser.values().contains(name)) {
                out.println("用户已在别的客户端登录，请重新输入\n");
            } else {
                out.println("登录成功！\n");
                onlineUser.put(socket, name);
                System.out.println("玩家["+name+"]已上线....");
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    private void mainPage(Socket socket) {
        String functionFlag=null;
        try {
            PrintWriter out =new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true);
            BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
            allOut.put(socket,out);
            allInput.put(socket,in);
            out.println("****************************");
            out.println("欢迎赌神光临");
            while (true) {
                out.println("****************************");
                out.println("1、查看大厅人数\t2、匹配（进行游戏）\t3、私聊\t4、注销账号\t5、修改密码\t6、大厅发消息\t7、查看战绩\t输入esc退出");
                functionFlag = in.readLine();
                switch (functionFlag) {
                    case "1":
                        StringBuilder stringBuilder = new StringBuilder();
                        for (String name:onlineUser.values()) {
                            stringBuilder.append(name+" ");
                            User user=userDao.findUserByusername(name);
                            if (user.getSegment()<11) {
                                stringBuilder.append("小白"+user.getSegment()+"星");
                            } else if (user.getSegment()>10&& user.getSegment()<21) {
                                stringBuilder.append("赌鬼"+(user.getSegment()-10)+"星");
                            }else if (user.getSegment()>20&& user.getSegment()<31) {
                                stringBuilder.append("赌王"+(user.getSegment()-20)+"星");
                            }else if (user.getSegment()>30&& user.getSegment()<41) {
                                stringBuilder.append("赌圣"+(user.getSegment()-30)+"星");
                            }else {
                                stringBuilder.append("赌神"+(user.getSegment()-40)+"星");
                            }
                            stringBuilder.append(",");
                        }
                        stringBuilder.deleteCharAt(stringBuilder.length()-1);
                        out.println(stringBuilder);
                        break;
                    case "2":
                        out.println("正在匹配....");
                        apartment.put(socket, onlineUser.get(socket));
                        lock.lock();
                        try {
                            if (apartment.size() != PLAYERS_PER_GAME) {
                                waitingThread.put(socket,new MyThread(condition,Thread.currentThread(),lock));
                                condition.await();
                            }else {
                                Map<Socket, String> players = new HashMap<>();
                                for (Socket s:apartment.keySet()) {
                                    players.put(s,apartment.get(s));
                                    apartment.remove(s);
                                }
                                threadPool.submit(() -> {
                                    try {
                                        Thread gameThread = new Thread(new roomThread(players, allOut, allInput,waitingThread));
                                        gameThread.start();
                                        gameThread.join();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                });
                                waitingThread.put(socket,new MyThread(condition,Thread.currentThread(),lock));
                                condition.await();
                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        } finally{
                            lock.unlock();
                        }
                        break;
                    case "3":
                        Socket aimSocket=null;
                        out.println("请输入对方的名字");
                        String name=in.readLine();
                        for (Socket s:onlineUser.keySet()) {
                            if (onlineUser.get(s).equals(name)) {
                                aimSocket=s;
                            }
                        }
                        if (aimSocket == null) {
                            out.println("对方不在线");
                        }else {
                            out.println("请输入内容");
                            String content=in.readLine();
                            PrintWriter aimOut =new PrintWriter(aimSocket.getOutputStream(),true);
                            aimOut.println("私聊："+onlineUser.get(socket)+"-->"+content);
                        }
                        break;
                    case "4":
                        String dName=onlineUser.get(socket);
                        int flag = userDao.deleteUser(dName);
                        if (flag == 1) {
                            onlineUser.remove(socket);
                            System.out.println("用户"+dName+"注销成功");
                            out.println("账号注销成功!");
                            Thread thread = Thread.currentThread();
                            thread.interrupt();
                        }else {
                            out.println("注销失败");
                        }
                        break;
                    case "5":
                        out.println("请输入您注册的电话号码：");
                        String phoneNumber = in.readLine();
                        User user=userDao.findPasswordByPhone(phoneNumber);
                        if (user ==null) {
                            out.println("号码不存在！");
                        }else {
                            out.println("请输入验证码：");
                            PhoneCode phonecode = new PhoneCode();
                            String code = phonecode.getCode();
                            phonecode.sendCode(phoneNumber,code,2);
                            for (int i = 0;i<3;i++) {
                                if (code.equals(in.readLine())) {
                                    out.println("请输入您新密码");
                                    String newPassword = in.readLine();
                                    boolean updateFlag = userDao.updatePasswordByPhone(phoneNumber,newPassword);
                                    if (updateFlag) {
                                        out.println("修改成功！");
                                    } else {
                                        out.println("修改失败！");
                                    }
                                    break;
                                } else {
                                    out.println("验证码错误,还有" + (3 - (i + 1)) + "次机会");
                                }
                            }
                        }
                        break;
                    case "6":
                        out.println("请输入内容");
                        String content=in.readLine();
                        for (Socket s:onlineUser.keySet()) {
                            PrintWriter aimOut =new PrintWriter(s.getOutputStream(),true);
                            aimOut.println("大厅消息："+onlineUser.get(socket)+"-->"+content);
                        }
                        break;
                    case "7":
                        List<Record> records=userDao.findRecordByName(onlineUser.get(socket));
                        StringBuilder stringBuilder1 = new StringBuilder();
                        User user1=userDao.findUserByusername(onlineUser.get(socket));
                        if (user1.getSegment()<11) {
                            stringBuilder1.append("小白"+user1.getSegment()+"星");
                        } else if (user1.getSegment()>10&& user1.getSegment()<21) {
                            stringBuilder1.append("赌鬼"+(user1.getSegment()-10)+"星");
                        }else if (user1.getSegment()>20&& user1.getSegment()<31) {
                            stringBuilder1.append("赌王"+(user1.getSegment()-20)+"星");
                        }else if (user1.getSegment()>30&& user1.getSegment()<41) {
                            stringBuilder1.append("赌圣"+(user1.getSegment()-30)+"星");
                        }else {
                            stringBuilder1.append("赌神"+(user1.getSegment()-40)+"星");
                        }
                        out.println("当前段位："+stringBuilder1);
                        out.println("\t用户\t\t\t\t\t当局玩家\t\t\t\t\t\t当局时间\t\t\trecord");
                        for (Record r:records) {
                            out.println(r.getUser()+"\t"+r.getPlayAll()+"\t"+r.getDate().toString()+"\t"+r.getOutcome());
                        }
                        break;
                    case "esc":
                        out.println("esc");
                        System.out.println("玩家["+onlineUser.get(socket)+"]已下线");
                        onlineUser.remove(socket);
                        Thread thread = Thread.currentThread();
                        thread.interrupt();
                    default:
                        out.println("输入无效！");
                }
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
            }
        }catch (java.net.SocketException e) {
            System.out.println("用户连接已断开。");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            onlineUser.remove(socket);
        }
    }

}
